package com.eduagent.xwqeduagent.utils.oj;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 在线评测服务实现类
 */
@Service
public class JudgeServiceImpl implements JudgeService {

    private static final Logger logger = LoggerFactory.getLogger(JudgeServiceImpl.class);

    @Autowired
    private JudgeClient judgeClient;

    @Override
    public boolean checkAuthentication() {
        try {
            return judgeClient.authenticate();
        } catch (IOException e) {
            logger.error("认证检查失败", e);
            return false;
        }
    }

    @Override
    public boolean checkAuthorization() {
        try {
            return judgeClient.authorize();
        } catch (IOException e) {
            logger.error("授权检查失败", e);
            return false;
        }
    }

    @Override
    public JudgeSubmissionResponse submitCode(String sourceCode, int languageId, String stdin, String expectedOutput, boolean wait) throws IOException {
        JudgeSubmission submission = new JudgeSubmission();
        submission.setSourceCode(sourceCode);
        submission.setLanguageId(languageId);
        submission.setStdin(stdin);
        submission.setExpectedOutput(expectedOutput);

        return judgeClient.createSubmission(submission, wait, false);
    }

    @Override
    public JudgeSubmissionResponse submitCode(String sourceCode, String language, String stdin, String expectedOutput, boolean wait) throws IOException {
        // 获取语言ID
        Integer languageId = getLanguageIdByName(language);
        if (languageId == null) {
            throw new IllegalArgumentException("不支持的编程语言: " + language);
        }

        return submitCode(sourceCode, languageId, stdin, expectedOutput, wait);
    }

    @Override
    public JudgeSubmissionResponse submitMultiFiles(String mainFile, List<String> additionalFiles, String compileScript, String runScript, String stdin, String expectedOutput, boolean wait) throws IOException {
        // 读取主文件
        Path mainPath = Paths.get(mainFile);
        String mainContent = new String(Files.readAllBytes(mainPath));
        
        // 读取附加文件，并创建一个文件名到内容的映射
        Map<String, String> additionalFileContents = new HashMap<>();
        for (String file : additionalFiles) {
            Path path = Paths.get(file);
            String content = new String(Files.readAllBytes(path));
            additionalFileContents.put(path.getFileName().toString(), content);
        }
        
        // 创建一个包含所有文件的归档
        String archive = JudgeUtils.createArchive(mainPath.getFileName().toString(), mainContent, additionalFileContents);
        
        // 创建提交
        JudgeSubmission submission = new JudgeSubmission();
        submission.setSourceCode(archive);
        submission.setAdditionalFiles(Boolean.TRUE);
        submission.setCompilerOptions(compileScript); // 使用compilerOptions存储编译脚本
        submission.setCommandLineArguments(runScript); // 使用commandLineArguments存储运行脚本
        submission.setStdin(stdin);
        submission.setExpectedOutput(expectedOutput);
        
        return judgeClient.createSubmission(submission, wait, false);
    }

    @Override
    public List<JudgeSubmissionResponse> submitBatchCode(List<JudgeSubmission> submissions, boolean wait) throws IOException {
        return judgeClient.createBatchSubmissions(submissions, wait, false);
    }

    @Override
    public JudgeSubmissionResponse getSubmission(String token) throws IOException {
        return judgeClient.getSubmission(token, false, null);
    }

    @Override
    public JudgeSubmissionResponse getSubmission(String token, String fields) throws IOException {
        return judgeClient.getSubmission(token, false, fields);
    }

    @Override
    public List<JudgeSubmissionResponse> getBatchSubmissions(List<String> tokens) throws IOException {
        String tokenStr = String.join(",", tokens);
        return judgeClient.getBatchSubmissions(tokenStr, false, null);
    }

    @Override
    public List<JudgeSubmissionResponse> getBatchSubmissions(List<String> tokens, String fields) throws IOException {
        String tokenStr = String.join(",", tokens);
        return judgeClient.getBatchSubmissions(tokenStr, false, fields);
    }

    @Override
    public boolean deleteSubmission(String token) throws IOException {
        JudgeSubmissionResponse response = judgeClient.deleteSubmission(token);
        return response != null;
    }

    @Override
    public Map<String, Integer> getSupportedLanguages() {
        Map<String, Integer> languages = new HashMap<>();
        // 按照常用语言填充映射表
        languages.put("c", 50);              // C (GCC 9.2.0)
        languages.put("cpp", 54);            // C++ (GCC 9.2.0)
        languages.put("java", 62);           // Java (OpenJDK 13.0.1)
        languages.put("python", 71);         // Python (3.8.1)
        languages.put("javascript", 63);     // JavaScript (Node.js 12.14.0)
        languages.put("go", 60);             // Go (1.13.5)
        languages.put("ruby", 72);           // Ruby (2.7.0)
        languages.put("rust", 73);           // Rust (1.40.0)
        languages.put("csharp", 51);         // C# (Mono 6.6.0.161)
        languages.put("php", 68);            // PHP (7.4.1)
        languages.put("kotlin", 78);         // Kotlin (1.3.70)
        languages.put("swift", 83);          // Swift (5.2.3)
        languages.put("pascal", 67);         // Pascal (FPC 3.0.4)
        languages.put("typescript", 74);     // TypeScript (3.7.4)
        return languages;
    }

    @Override
    public Integer getLanguageIdByName(String languageName) {
        return getSupportedLanguages().get(languageName.toLowerCase());
    }

    @Override
    public Object getLanguagesList(boolean all) throws IOException {
        return judgeClient.getLanguages(all);
    }

    @Override
    public Object getLanguageInfo(int languageId) throws IOException {
        return judgeClient.getLanguage(languageId);
    }

    @Override
    public Object getStatusList() throws IOException {
        return judgeClient.getStatuses();
    }

    @Override
    public Object getSystemInfo() throws IOException {
        return judgeClient.getSystemInfo();
    }

    @Override
    public Object getConfigInfo() throws IOException {
        return judgeClient.getConfigInfo();
    }

    @Override
    public Object getStatistics(boolean invalidateCache) throws IOException {
        return judgeClient.getStatistics(invalidateCache);
    }

    @Override
    public Object getWorkers() throws IOException {
        return judgeClient.getWorkers();
    }

    @Override
    public Object getAbout() throws IOException {
        return judgeClient.getAbout();
    }

    @Override
    public Object getVersion() throws IOException {
        return judgeClient.getVersion();
    }

    @Override
    public Object getLicense() throws IOException {
        return judgeClient.getLicense();
    }
} 